const express = require('express')
// 导入用于生成jwt字符串的包(加密)
const jwt = require('jsonwebtoken')
// 导入用于解析jwt字符串的包(解密)
const expressJWT = require('express-jwt')

const server = express()


// 定义secret密钥(自定义密钥,用于加密和解密)，建议名命为secretKey
const secretKey = 'secret*&#12345'


// 客户端每次在访问那些有权限接口的时候，都需要主动通过请求头中的Authorization字段，值需要将前缀加上Bearer，将token字符串发送到服务器进行身份认证。
// 服务器可以通过express-jwt这个中间件，自动将客户端发送过来的token解析还原成JSON对象

/**
 * 1.  使用app.use()来注册中间件
 * 2.  expressJWT({secret:secretKey}) 用来解析token的中间件
 * 3.  .unless({path:正则表达式})用来指定哪些接口不需要访问权限
 * 4.  server.use(expressJWT({secret:secretKey}).unless({pat h:[/^\/api\//]})) //除了api的路由，都需要权限
 */

// 使用中间件解析客户端传来的数据
server.use(express.urlencoded({extended:false}))

server.use(expressJWT({ secret: secretKey }).unless( {path: [/^\/api\//]}))
// 当配置成功expressJWT()这个中间件之后，即可在指定有权限的接口中，使用req.user对象，来访问从JWT字符串中解析出来的用户信息了(req本身没有user属性)



server.post('/api/login',(req,res)=>{
    // 获取请求体中携带的参数
    const userInfo = req.body
    // 判断登录
    console.log(userInfo)
    // 登录失败
    if(userInfo.name!=='admin'||userInfo.password!=='admin123'){
        return res.send({
            status:400,
            msg:'登录失败！'
        })
    }
    // 登录成功
    // 调用jwt.sign()方法生成jwt字符串，并通过token属性发送给客户端
    // jwt.sign( {用户的信息对象}， 加密的密钥， {配置对象(配置当前token有效期)} )
    const tokenStr = jwt.sign( {name:userInfo.name}, secretKey, { expiresIn: '10s' } )
    return res.send({
        status:200,
        msg:'登录成功！',
        token:tokenStr
    })
})



// 有权限的路由
server.get('/admin/getinfo',(req,res)=>{
    res.send({
        status:200,
        msg:'获取信息成功！',
        data:req.user
    })
})

// 若客户端发送过来的token字符串过去或者不合法，会产生一个解析失败的错误，利用错误中间件，捕获这个错误并进行相关处理
server.use((err,req,res,next)=>{
    // token解析失败导致的错误
    if(err.name === 'UnauthorizedError'){
        return res.send({
            status:401,
            msg:'无效的token'
        })
    }
    // 其他的错误
    return res.send({
        status:500,
        msg:'未知错误'
    })
})



server.listen(80,()=>{
    console.log('http://127.0.0.1')
})